package cn.jasonone.jasonfx.interceptor;

import cn.jasonone.jasonfx.entity.Optional;
import cn.jasonone.jasonfx.util.ExceptionUtil;
import lombok.AllArgsConstructor;
import lombok.Setter;
import net.sf.cglib.proxy.MethodProxy;

@AllArgsConstructor
public class InterceptorChain {
	private ControllerInterceptor interceptor;
	@Setter
	private InterceptorChain next;

	/**
	 * 追加到控制器链
	 * 
	 * @param interceptor
	 */
	public boolean append(ControllerInterceptor interceptor) {
		try {
			Class<? extends ControllerInterceptor> preInterceptor = interceptor.preInterceptor();
			if (preInterceptor.isInstance(interceptor)) {
				next = new InterceptorChain(interceptor, null);
				return true;
			} else {
				if (next != null) {
					return next.append(interceptor);
				}
			}
			return false;
		} catch (Throwable e) {
			throw ExceptionUtil.wrapJasonFxException(e);
		}
	}

	/**
	 * 检测拦截器链中是否包含指定拦截器
	 * 
	 * @param type 拦截器类型
	 * @return boolean
	 */
	public boolean isInterceptor(Class<? extends ControllerInterceptor> type) {
		if (type.isInstance(interceptor)) {
			return true;
		}
		if (next == null)
			return false;
		return next.isInterceptor(type);
	}

	/**
	 * 方法拦截
	 * 
	 * @param obj         代理对象
	 * @param proxy       代理方法
	 * @param args        方法入参
	 * @param returnValue 方法返回值,仅当{@link ControllerInterceptor#intercept(Object, MethodProxy, Object[], Optional)}方法返回false时有效
	 * @throws Throwable
	 */
	public void intercept(Object obj, MethodProxy proxy, Object[] args, Optional<Object> returnValue) throws Throwable {
		if (interceptor.isInterceptor(obj, proxy)) {
			interceptor.intercept(obj, proxy, args, returnValue, next);
		}
	}

}
